package com.tc.zigbee.entity;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.tc.zigbee.device.config.DeviceConfigManager;
import com.tc.zigbee.entity.device.ZigbeeDevice;
import com.tc.zigbee.ha.HAConstants;
import com.tc.zigbee.ha.Meta;
import com.tc.zigbee.mt.ZigbeeManager;
import com.tc.zigbee.zcl.ZclConstants;
import com.tc.zigbee.zcl.command.DataValue;


public class Endpoint {
//	String name;
//	1  1  1  2  1  2  1 
//	Length = 0x06-4E  Cmd0 = 0x45  Cmd1 = 0x84  SrcAddr  Status  NwkAddr  Len 
//	1  2  2  1 
//	Endpoint  ProfileId  DeviceId  DeviceVersion 
//	1  0-32  1  0-32 
//	NumInClusters  InClusterList  NumOutClusters  OutClusterList 
//	
//	
	ZigbeeManager manager;
	ZNode parent;
	ZigbeeDevice device;
	public ZigbeeDevice getDevice() {
		return device;
	}
	public Endpoint(ZNode p, byte eid,	ZigbeeManager m){
		parent = p;
		endpointId = eid;
		this.manager = m;
	}
	public ZNode getParent() {
		return parent;
	}
	public void setParent(ZNode parent) {
		this.parent = parent;
	}
	public byte getEndpointId() {
		return endpointId;
	}
	public void setEndpointId(byte endpointId) {
		this.endpointId = endpointId;
	}
	public short getProfileId() {
		return profileId;
	}
	public void setProfileId(short profileId) {
		this.profileId = profileId;
	}
	public short getDeviceId() {
		return deviceId;
	}
	public void setDeviceId(short deviceId) {
		this.deviceId = deviceId;
	}
	public byte getDeviceVersion() {
		return deviceVersion;
	}
	public void setDeviceVersion(byte deviceVersion) {
		this.deviceVersion = deviceVersion;
	}
	public byte getNumInClusters() {
		return numInClusters;
	}
	public void setNumInClusters(byte numInClusters) {
		this.numInClusters = numInClusters;
	}
	public List<Short> getInClusters() {
		return inClusters;
	}
	public void setInClusters(List<Short> inClusters) {
		this.inClusters = inClusters;
	}
	public byte getNumOutClusters() {
		return numOutClusters;
	}
	public void setNumOutClusters(byte numOutClusters) {
		this.numOutClusters = numOutClusters;
	}
	public List<Short> getOutClusters() {
		return outClusters;
	}
	public void setOutClusters(List<Short> outClusters) {
		this.outClusters = outClusters;
	}
	byte endpointId;
	short profileId;
	short deviceId;
	byte deviceVersion;
	byte latency;
//	public String getName() {
//		return name;
//	}
//	public void setName(String name) {
//		this.name = name;
//	}
	public byte getLatency() {
		return latency;
	}
	public void setLatency(byte latency) {
		this.latency = latency;
	}
	byte numInClusters;
	List<Short> inClusters = new LinkedList<Short>();
	byte numOutClusters;
	List<Short> outClusters = new LinkedList<Short>();
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		if(device != null && device.getName() != null && !device.getName().trim().equals(""))
			return device.getName();
//		if(profileId == HAConstants.ZCL_HA_PROFILE_ID){
////			String typeName = Meta.deviceTypeNames.get(deviceId);
//			if(typeName != null && !typeName.trim().equals(""))
//				return typeName + "[" + endpointId + "]";
//		}
		return "[" + endpointId + "]";
	}
	public String description(){
		String typeName = "";
		if(profileId == HAConstants.ZCL_HA_PROFILE_ID)
			typeName = deviceId + "";
		String rst = "NemtworkAddress:" + parent.getNwkAddress()
		+ "\n" + "endpoint: " + endpointId
		
		
		+ "\n" + "profileId: " + profileId
		+ "\n" + "deviceId:" + typeName + "[" + deviceId + "]"
		+ "\n" + "deviceVersion:" + deviceVersion
		+ "\n" ;
		for(short i : inClusters){
			String cn = ZclConstants.clusterNames.get(i);
			rst = rst + "\n" + cn + "[" + i + "]"  ;
		}
		rst = rst + "\n" + "clusters:";
		for(short i : outClusters){
			String cn = ZclConstants.clusterNames.get(i);
			rst = rst +  "\n" + cn + "[" + i + "]" ;
		}
		return rst;
	}
	Map<Short,Map<Short, DataValue>> attributeMap = new HashMap<Short,Map<Short, DataValue>>();
	public void setAttribute(short cluster, short attributeId, DataValue value){
		Map<Short, DataValue> ca = attributeMap.get(cluster);
		if(ca == null)
		{
			ca = new HashMap<Short, DataValue>();
			attributeMap.put(cluster, ca);
		}
		ca.put(attributeId, value);
	}
	
	public DataValue getAttribute(short cluster, short attributeId){
		Map<Short, DataValue> ca = attributeMap.get(cluster);
		if(ca == null)
		{
			return null;
		}
		return ca.get(attributeId);
	}
	public void fill(Endpoint ep){
		this.setDeviceId(ep.getDeviceId());
		this.setDeviceVersion(ep.getDeviceVersion());
		this.setInClusters(ep.getInClusters());
		this.setNumInClusters(ep.getNumInClusters());
		this.setNumOutClusters(ep.getNumOutClusters());
		this.setInClusters(ep.getInClusters());
		this.setOutClusters(ep.getOutClusters());
		this.setProfileId(ep.getProfileId());
	}
	public ZigbeeDevice createDevice() {
		if(this.getProfileId() != HAConstants.ZCL_HA_PROFILE_ID)
			return null;
		Class<? extends ZigbeeDevice> type = Meta.deviceTypes.get(this.deviceId);
		if(type == null)
			return null;
		try {
			this.device = type.getConstructor(Endpoint.class,ZigbeeManager.class).newInstance(this, manager);
			DeviceConfigManager.getInstance().match(device);
			return device;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}
}
